#ifndef _CLIENTGEOMETRY_H_
#define _CLIENTGEOMETRY_H_

#include <buildspec.h>

#include <boost/cstdint.hpp>
#include <boost/optional.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/ptr_container/ptr_list.hpp>
#include <boost/shared_ptr.hpp>

#include <Geometry/StreamableGeometry.h>
#include <Geometry/ClientSimplexProperty.h>
#include <Geometry/IFileSerialisable.h>
#include <Geometry/ObjectArchive.h>
#include <Client/ClientUtils/Network/TableAttributeDesc.h>

namespace GST {

	//forward declaration (may restructure target)
	namespace ClientGUI {
		struct UploadPackage;
	}		

namespace Geometry{

	/**
	  * this class handles the forward declared pointer 
	  */
	struct UploadPackageRef
	{
		ClientGUI::UploadPackage * ref;
		int refCount;

		UploadPackageRef(ClientGUI::UploadPackage * ref)
			: refCount(0)
			, ref(ref)
		{
		}
	};

	/**
	 * Class for the geometry on clientside.
	 */
class GST_API_EXPORT ClientGeometry 
	: public StreamableGeometry
	, public IFileSerialisable
{	
	
protected:
	ClientGeometry();
	ClientGeometry(IGeometry::GeometryType type);

public:
	
	///@name typedefs
	//@{
	typedef boost::ptr_vector<ClientSimplexProperty>				SmplxPropertyList;
	typedef boost::shared_ptr<SmplxPropertyList>					SmplxPropertyListPtr;
	typedef SmplxPropertyList::iterator								SmplxPropertyItr;
	/**
	  * The Simplex Property Matching list is for geometry sending formats that aren't separated in geometry stream and
	  * property stream (e.g. Gocad ASCII format). Then a Simplex Property Matching list represents
	  *		#- which property in geometry stream is equivalent with which property in database (matching by name)
	  *		#- only the properties which are listed in the matching list are stored. All the other values will be ignored and became NULL in database
	  *	
	  * The matching list is simple a key value List. The encoding of the matching list is the following:
	  * - key: local property name
	  * - value: db property name
	  */
	typedef std::map< std::string,std::string > SimplexPropMatchingList;
	typedef boost::shared_ptr<SimplexPropMatchingList> SimplexPropMatchingListPtr;
	//@}

	///@name Client called members (lib independend)
	//@{
	virtual unsigned int addSimplexProperty(
		const std::string &name,
		ClientSimplexProperty::PropertyType PropertyType,
		unsigned int dims,
		ClientSimplexProperty::PropertyAlignment alignment
		= Geometry::VERTEX_ALIGNED)
		= 0;
	virtual unsigned int addSimplexProperty(const ClientSimplexProperty & p) = 0;
	virtual unsigned int addSimplexProperty(const ClientUtils::TableAttributeDesc & p);
	virtual SmplxPropertyListPtr getProperties() const = 0;
	virtual void setProperties(const SmplxPropertyListPtr & newlist) = 0;

	virtual std::string constructGeometryFileName(const FileType & filetype, const std::string & prefix = std::string(), const std::string suffix = std::string()) const;
	virtual std::string constructPropertyFileName(const FileType & filetype, const std::string & prefix = std::string(), const std::string suffix = std::string()) const;
	virtual std::string constructArchiveFileName(const FileType & filetype, const std::string & prefix = std::string(), const std::string suffix = std::string()) const;
	virtual std::string constructFileStamp(const FileType & filetype, const std::string & prefix = std::string(), const std::string suffix = std::string()) const;
	virtual void SaveGeometry(const std::string & filename, const FileType & filetype) = 0;
	virtual void SaveProperty(const std::string & filename, const FileType & filetype) = 0;
	virtual void SaveArchive(const std::string & filename, const FileType & filetype);

	virtual void setSimplexPropertyMatchList(SimplexPropMatchingListPtr matchList);
	virtual SimplexPropMatchingListPtr getSimplexPropertyMatchList() const;

	virtual boost::optional<boost::uint64_t> GetGeometryFileStart() const;
	virtual boost::optional<boost::uint64_t> GetGeometryFileEnd() const;
	//@}

	///@name getters/setters for archive
	//@{
	virtual const GeometryTypes& getType() const;
	virtual void setType(const IGeometry::GeometryType& geomtype);
	virtual void setName(const std::string & name);
	virtual void setOriginalName(const std::string& name);
	virtual void setColor(const IGeometry::Color& color);
	virtual void setTransparency( const IGeometry::TransparencyCode& code );
	virtual void setLockid(const std::string & lockid);
	virtual std::string getLockid() const;
	virtual bool isLocked() const;
	virtual void setFileType(const IFileSerialisable::FileType & ftype);
	virtual IFileSerialisable::FileType GetFileType() const;
	virtual void setGeometryFile(const std::string & fileName);
	virtual std::string GetGeometryFile() const;
	virtual void setPropertyFile(const std::string & fileName);
	virtual std::string GetPropertyFile() const;
	virtual void addObjectPropertyValue(const std::string name, const std::string & value);
	virtual void dropObjectProperty(const std::string name);
	virtual std::string getObjectPropertyValue( const std::string & propertyName ) const;
	virtual ObjectArchive::VariousPropertyMap GetObjProperties() const;
	virtual void clearObjectProperties();
	virtual void setObjProperties(const ObjectArchive::VariousPropertyMap & kvmap);
	bool RenameObjProperty( const std::string & oldName, const std::string & newName );
	void setSrs(GST::Geometry::SRSPtr val);
	
	virtual void setArchiveFileName(const std::string & fileName);
	virtual std::string GetArchiveFileName() const;
	//@}

	ObjArchivePtr GetArchive() const;
	ObjArchivePtr GetOrCreateArchive();
	void setArchive(boost::shared_ptr<ObjectArchive> a);
	void setArchiveLowPriority(boost::shared_ptr<ObjectArchive> a);

	///@name StreamableGeometry members
	//@{
	virtual Geometry::SRSPtr GetSRS() const;
	virtual IGeometry::TransparencyCode GetTransparency() const;
	virtual IGeometry::Color GetColor() const;
	virtual std::string GetName() const;
	virtual std::string GetOriginalName() const;
	virtual KeyValueListPtr GetVariousProperties() const;
	//@}

protected:

	///@name helpers
	//@{
	std::string ExtraktFileNameFromPath(const std::string & filename) const;
	//@}
	
	///@name members
	//@{	
	ObjArchivePtr archive;
	std::string archive_filename;
	SimplexPropMatchingListPtr simplexPropertyMatchingList;
	GeometryTypes geomtype;		
	//@}
	
};
typedef boost::shared_ptr<ClientGeometry> ClientGeometryPtr;
typedef std::vector<ClientGeometryPtr> ClientGeometryList;
typedef boost::shared_ptr<ClientGeometryList> ClientGeometryListPtr;


//------------------------------------------------------------------------------

class GST_API_EXPORT NullGeometry
	: public ClientGeometry
{
public:
	NullGeometry();

	NullGeometry(IGeometry::GeometryType type);

	unsigned int addSimplexProperty(
		const std::string &name,
		ClientSimplexProperty::PropertyType PropertyType,
		unsigned int dims,
		ClientSimplexProperty::PropertyAlignment alignment
		= Geometry::VERTEX_ALIGNED) override;
	virtual unsigned int addSimplexProperty(const ClientSimplexProperty & p);

	virtual SmplxPropertyListPtr getProperties() const;
	virtual void setProperties(const SmplxPropertyListPtr & newlist);

	virtual void SaveGeometry(const std::string & filename, const FileType & filetype);
	virtual void SaveProperty(const std::string & filename, const FileType & filetype);

	virtual bool serializeGeometry(std::ostream & os) const;
	virtual bool serializeSimplexPropertyValues(std::ostream & os) const;
	virtual bool serializeSimplexPropertyDescription(std::ostream & os) const;

	virtual void saveToFile(const std::string & filename, const FileType & filetype);
	virtual void loadFromFile(const std::string & filename, const FileType & filetype);
};


}// namespace Geometry
}// namespace GST


#endif  //_CLIENTGEOMETRY_H_
